smite-ir: Introduce affine state variables for strict state enforcement#97
Conversation
531ca61 to
798752a
Compare
| let candidate_to_resolve = chosen_candidate | ||
| .unwrap_or_else(|| candidates.last().unwrap()) | ||
| .clone(); | ||
| return self.resolve_candidate(candidate_to_resolve); | ||
| } |
There was a problem hiding this comment.
As discussed here, this is an anti-pattern and we should modify the function's signature to return an Option<usize> instead of intentionally generating an invalid instruction.
There was a problem hiding this comment.
Decided to panic instead, because that's in-line with the current behavior. SpliceMutator will require this behavior to change as a whole, so I'll modify it if and when we need it instead of front-loading the complexity in this PR.
34528b0 to
18143e2
Compare
|
Rebased on top of the latest master to resolve merge conflicts. |
825f42b to
982d207
Compare
|
Had to rebase again to solve a merge conflict. |
982d207 to
5d3fd3c
Compare
morehouse
left a comment
There was a problem hiding this comment.
The code looks correct to me now. All my remaining comments are nits related to style or missing tests.
Also the commit message for d7f0788 is slightly out-of-date and the first bullet point should be updated to:
- Add `SendOpenChannel` operation: Consumes a composed `OpenChannelMessage`
and outputs a `SentOpenChannel` affine variable.
cda5521 to
9cf3cc8
Compare
|
Had to rebase (yet again) to resolve a merge conflict. |
9707aaf to
74e6a8c
Compare
74e6a8c to
466fd5f
Compare
Add `SentOpenChannel` to the `Variable` and `VariableType` enums. Unlike standard data variables which can be referenced infinitely, this new type is designed to be "affine" (single-use). Affine variables represent strict topological locks in the LN state machine (e.g., `SentOpenChannel` ensures a channel is actively pending before allowing a `RecvAcceptChannel`).
Update `pick_variable` with a dedicated branch for affine types. Unlike data variables which use a probabilistic 75/15/10 strategy, affine types use deterministic tip-tracking.
Update `Program::validate()` to enforce the single-use nature of affine state variables, preventing mutators from generating impossible state-machine sequences. Add a validation rule: An affine variable cannot be consumed as an input more than once. This prevents mutators from reusing old state variables to bypass protocol ordering.
Affine variables carry no data and act purely as state tokens, so swapping them yields no practical fuzzing value. While at it, add a test to verify the change.
Introduce a dedicated `OpenChannelMessage` variable, separating it from the generic `Message` type. This strongly types the output of `BuildOpenChannel`, and is used as an input to `SendOpenChannel` in a subsequent commit. This prevents `InputSwapMutator` from swapping it with a different message type, possibly causing a timeout.
Introduce the strict topological link for channel initialization. - Add `SendOpenChannel` operation: Consumes a composed `OpenChannelMessage` and outputs a `SentOpenChannel` affine variable. - Modify `RecvAcceptChannel`: Now requires `SentOpenChannel` as an input, enforcing that the fuzzer cannot wait for an `accept_channel` unless it actually opened a channel first. - Update unit tests to accommodate the new input requirements for `RecvAcceptChannel`.
Update `OpenChannelGenerator` to utilize the newly introduced strict topological operations: 1. Replace `SendMessage` with `SendOpenChannel`, which consumes the `Message` payload and outputs a `SentOpenChannel`. 2. Update `RecvAcceptChannel` to consume the `SentOpenChannel`. 3. Update tests to accommodate the non-void output of `SendOpenChannel`.
Add tests to verify the data-flow rules introduced for state tracking.
466fd5f to
a6032db
Compare
morehouse
left a comment
There was a problem hiding this comment.
LGTM. Also did a 15 minute smoke test fuzzing LDK, and no issues.
| Self::LoadChannelType(v) => write!(f, "LoadChannelType({v})"), | ||
| Self::LoadTargetPubkeyFromContext => write!(f, "LoadTargetPubkeyFromContext()"), | ||
| Self::LoadChainHashFromContext => write!(f, "LoadChainHashFromContext()"), | ||
| Self::RecvAcceptChannel => write!(f, "RecvAcceptChannel()"), |
There was a problem hiding this comment.
Now that RecvAcceptChannel takes SentOpenChannel as input, the empty parens should be removed here and the corresponding tests, comments etc should also be updated accordingly
This PR introduces affine (single-use) types to the IR to strictly enforce the Lightning Network state machine during fuzzing, in order to prevent timeout hangs caused by semantically invalid mutation sequences.
Solves issue #75, see it for more details.